package cn._2dland.uploader.task
{
	import cn._2dland.uploader.events.TaskEvent;
	import cn._2dland.uploader.utils.UploaderUtils;
	
	import flash.display.Loader;
	import flash.events.DataEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.filesystem.File;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.utils.getTimer;

	[Event(name="ready",type="cn._2dland.uploader.events.TaskEvent")]
	[Event(name="failed",type="cn._2dland.uploader.events.TaskEvent")]
	[Event(name="complete",type="cn._2dland.uploader.events.TaskEvent")]
	[Event(name="progress",type="flash.events.ProgressEvent")]

	public class QQUploadTask extends EventDispatcher
	{
		public var title:String;
		public var cat:String;
		public var tags:String;
		public var desc:String;

		public var path:String;
		public var size:String;

		public var status:String;
		public var speed:Number = 0;

		private var _file:File;
		private var _qq:String;
		private var _fid:String;
		private var _vid:String;

		private var _loader:URLLoader = null;
		private var _running:Boolean = false;
		private var _lastTime:Number = 0;
		private var _lastSize:Number = 0;

		public function QQUploadTask(f:File){
			this._file = f;

			this.title = f.name.substring(0, f.name.lastIndexOf("."));
			this.cat = "动漫";
			this.tags = "动漫";
			this.desc = this.title;

			this.path = f.nativePath;
			this.size = UploaderUtils.formatFileSize(f.size);

			this.status = UploadTaskStatus.WAIT;
		}

		/** 开始上传 */
		public function exec(qq:String):void {
			if(_running) return;
			_running = true;

			_qq = qq;
			this.status = UploadTaskStatus.START;

			_loader = new URLLoader();
			var readyReq:URLRequest = new URLRequest("http://cgi.video.qq.com/v1/upload/upready");
			readyReq.method = URLRequestMethod.POST;

			var params:URLVariables = new URLVariables();
			params.type = 0;
			params.title = title;
			params.tags = tags;
			params.cat = cat;
			params.desc = desc;
			params.fsize = _file.size;
			readyReq.data = params;
			
			_loader.addEventListener(Event.COMPLETE, readyCompleteHandler);
			_loader.load(readyReq);
		}

		/** 取消上传 */
		public function cancel():void {
			_file.cancel();
			release();

			_running = false;
			status = UploadTaskStatus.FAILED;
			dispatchEvent(new TaskEvent(TaskEvent.FAILED, "User canceled"));
		}

		public function get vid():String {
			return this._vid;
		}

		private function upload():void {
			this.status = UploadTaskStatus.RUNNING;

			var uploadReq:URLRequest = new URLRequest("http://uu.video.qq.com/v1/upload/upcvideo");
			uploadReq.method = URLRequestMethod.POST;
			var params:URLVariables = new URLVariables();
			params.type = 0;
			params.title = title;
			params.tags = tags;
			params.cat = cat;
			params.desc = desc;
			params.fsize = _file.size;
			params.fid = _fid;
			params.uin = _qq;
			params.vid = _vid;
			params.Upload = "Submit Query";
			uploadReq.data = params;

			_lastTime = getTimer();
			_lastSize = 0;

			_file.addEventListener(ProgressEvent.PROGRESS, uploadProgressHandler);
			_file.addEventListener(IOErrorEvent.IO_ERROR, uploadIOErrorHandler);
			_file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, uploadCompleteHandler);
			_file.upload(uploadReq);
		}

		protected function readyCompleteHandler(e:Event):void {
			_loader.removeEventListener(Event.COMPLETE, readyCompleteHandler);

			var readyXml:XML = new XML(_loader.data);
			_fid = readyXml.fid;
			_vid = readyXml.vid;
			
			_loader.close();
			_loader = null;

			dispatchEvent(new TaskEvent(TaskEvent.READY, _vid));
			upload();
		}

		protected function uploadProgressHandler(e:ProgressEvent):void {
			// 计算上传速度
			var currTime:Number = getTimer();
			var timeSeg:Number = currTime - _lastTime;
			if(timeSeg > 500){
				_lastTime = currTime;

				var sizeSeg:Number = e.bytesLoaded - _lastSize;
				_lastSize = e.bytesLoaded;

				this.speed = sizeSeg / timeSeg * 1000;
			}

			dispatchEvent(e);
		}

		protected function uploadIOErrorHandler(e:IOErrorEvent):void {
			this.status = UploadTaskStatus.FAILED;
			_running = false;
			release();
			dispatchEvent(new TaskEvent(TaskEvent.FAILED, "IO error"));
		}

		protected function uploadCompleteHandler(e:DataEvent):void {
			_running = false;
			release();

			var rx:XML = new XML(e.data);
			if(rx.s != "o"){
				this.status = UploadTaskStatus.FAILED;
				dispatchEvent(new TaskEvent(TaskEvent.FAILED, "Server rejected"));
			}
			else {
				this.status = UploadTaskStatus.COMPLETE;
				dispatchEvent(new TaskEvent(TaskEvent.COMPLETE, _vid));
			}
		}

		private function release():void {
			_file.removeEventListener(ProgressEvent.PROGRESS, uploadProgressHandler);
			_file.removeEventListener(IOErrorEvent.IO_ERROR, uploadIOErrorHandler);
			_file.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA, uploadCompleteHandler);
		}
	}
}